package com.zhangh.summer.admin.biz.org.impl;

import com.zhangh.summer.admin.biz.org.OrgBiz;
import com.zhangh.summer.admin.model.bo.OrgBO;
import com.zhangh.summer.admin.model.po.AdOrgPO;
import com.zhangh.summer.admin.model.bo.OrgQuery;
import com.zhangh.summer.admin.model.po.AdOrgPOExample;
import com.zhangh.summer.admin.model.po.AdUserPOExample;

import com.zhangh.summer.admin.support.aop.tx.MultiDs;
import com.zhangh.summer.admin.support.ds.common.MixedDS;
import com.zhangh.summer.admin.support.exception.BizException;
import com.zhangh.summer.admin.support.id.IdGen;
import com.zhangh.summer.admin.support.session.SysSession;
import com.zhangh.summer.admin.support.utils.BeanGenerator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @description: TODO
 * @author: zhanghui  zhanghlucky@163.com
 * @create: 2021-09-28 01:31
 **/
@Service
@Slf4j
public class OrgBizImpl implements OrgBiz {
    @Resource
    private MixedDS mixedDS;
    @Autowired
    private IdGen idGen;

    @Override
    @MultiDs
    public List<OrgBO> getOrgList(OrgQuery query) {
        AdOrgPOExample orgPOExample=new AdOrgPOExample();
        AdOrgPOExample.Criteria c=orgPOExample.createCriteria();
        if (StringUtils.isNotBlank(query.getOrgName())){
            c.andOrgNameLike("%"+query.getOrgName()+"%");
        }
        if (null!=query.getIsEnable()&&query.getIsEnable()){
            c.andIsEnableEqualTo(true);
        }
        c.andIsDelEqualTo(false);
        orgPOExample.setOrderByClause("priority asc ");
        List<AdOrgPO> orgPOList=this.mixedDS.txDs().mapper().selectByExample(orgPOExample);

        List<AdOrgPO> treeOrgPOList=orgPOList;
        //补父节点
        if (StringUtils.isNotBlank(query.getOrgName())){
            AdOrgPOExample allOrgPOExample=new AdOrgPOExample();
            allOrgPOExample.setOrderByClause("priority asc ");
            List<AdOrgPO> allOrgPOList=this.mixedDS.txDs().mapper().selectByExample(allOrgPOExample);
            List<Long> ids=new ArrayList<>();
            for (AdOrgPO menuPO : orgPOList) {
                List<Long> itemParentIDS=this.getParents(menuPO,allOrgPOList);
                ids.addAll(itemParentIDS);
            }
            List<Long> orgIDS=orgPOList.stream().map(AdOrgPO::getId).collect(Collectors.toList());
            ids.addAll(orgIDS);//聚合所有ID
            List<Long> treeOrgIDS = ids.stream().distinct().collect(Collectors.toList());//去重
            treeOrgPOList=allOrgPOList.stream().filter(item-> treeOrgIDS.contains(item.getId())).collect(Collectors.toList());
        }

        //root
        List<AdOrgPO> rootList=treeOrgPOList.stream().filter(item->item.getPid()==0).collect(Collectors.toList());
        //构建树结构
        List<OrgBO> OrgBOList=new ArrayList<>();
        for (AdOrgPO orgPO : rootList) {
            OrgBO OrgBO=this.buildOrg(orgPO,treeOrgPOList);
            OrgBOList.add(OrgBO);
        }
        return OrgBOList;
    }

    private List<Long> getParents(AdOrgPO orgPO,List<AdOrgPO> allOrgPOList){
        List<Long> list=new ArrayList<>();
        for (AdOrgPO adOrgPO : allOrgPOList) {
            if (orgPO.getPid()!=0&&orgPO.getPid().equals(adOrgPO.getId())){
                list.add(adOrgPO.getId());
                List<Long> childList=getParents(adOrgPO,allOrgPOList);
                list.addAll(childList);
            }
        }
        return list;
    }

    private OrgBO buildOrg(AdOrgPO root,List<AdOrgPO> orgPOList){
        OrgBO orgBO= BeanGenerator.copy(root,OrgBO.class);
        List<AdOrgPO> childPOList=orgPOList.stream().filter(item-> item.getPid().equals(root.getId())).collect(Collectors.toList());
        List<OrgBO> children=new ArrayList<>();
        for (AdOrgPO childPO : childPOList) {
            OrgBO childBO=this.buildOrg(childPO,orgPOList);
            children.add(childBO);
        }
        orgBO.setChildren(children.size()>0?children:null);
        return orgBO;
    }

    @Override
    @MultiDs
    public OrgBO getOrgBO(Long id) {
        AdOrgPO adOrgPO=this.mixedDS.txDs().mapper().selectByPrimaryKey(AdOrgPO.class,id);
        OrgBO orgBO=BeanGenerator.copy(adOrgPO,OrgBO.class);
        return orgBO;
    }

    @Override
    @MultiDs
    @Transactional
    public Long saveOrg(OrgBO orgBO) {
        AdOrgPO adOrgPO=BeanGenerator.copy(orgBO,AdOrgPO.class);
        adOrgPO.setId(idGen.getID());
        adOrgPO.setIsDel(false);
        if (orgBO.isOnRoot()){
            adOrgPO.setPid(0L);
            adOrgPO.setLevel(0);
        }else{
            OrgBO parent=this.getOrgBO(orgBO.getPid());
            adOrgPO.setLevel(parent.getLevel()+1);
        }
        double priority=this.getNewPriority(orgBO.getPid());
        adOrgPO.setPriority(priority);
        adOrgPO.setCreateBy(SysSession.getUser().getLoginName());
        adOrgPO.setCreateTime(new Date());
        adOrgPO.setUpdateBy(SysSession.getUser().getLoginName());
        adOrgPO.setUpdateTime(new Date());
        int c1=this.mixedDS.txDs().mapper().insert(adOrgPO);
        log.info("保存组织 id {}",adOrgPO.getId());
        return adOrgPO.getId();
    }
    private double getNewPriority(long pid){
        AdOrgPOExample example=new AdOrgPOExample();
        example.createCriteria().andPidEqualTo(pid);
        example.setOrderByClause("priority desc");
        AdOrgPO orgPO=this.mixedDS.txDs().mapper().selectFirstByExample(example);
        double priority=0.0;
        if (null!=orgPO){
            priority=orgPO.getPriority()+1;
        }
        return priority;
    }

    @Override
    @MultiDs
    @Transactional
    public int updateOrg(OrgBO orgBO) {
        AdOrgPO adOrgPO= BeanGenerator.copy(orgBO,AdOrgPO.class);
        if (!adOrgPO.getIsEnable()){
            this.setOrgDisable(adOrgPO.getId());
        }
        adOrgPO.setUpdateBy(SysSession.getUser().getLoginName());
        adOrgPO.setUpdateTime(new Date());
        int c1=this.mixedDS.txDs().mapper().updateByPrimaryKey(adOrgPO);
        log.info("更新组织 id  {}",adOrgPO.getId());
        return c1;
    }

    private void setOrgDisable(Long pid){
        AdOrgPOExample example=new AdOrgPOExample();
        example.createCriteria().andPidEqualTo(pid);
        List<AdOrgPO> orgPOList=this.mixedDS.txDs().mapper().selectByExample(example);
        for (AdOrgPO adOrgPO : orgPOList) {
            adOrgPO.setIsEnable(false);
            this.mixedDS.txDs().mapper().updateByPrimaryKey(adOrgPO);
            log.info("更新组织 name {} isEnable=false",adOrgPO.getOrgName());
            this.setOrgDisable(adOrgPO.getId());
        }
    }

    @Override
    @MultiDs
    @Transactional
    public int deleteOrg(Long id) {
        AdUserPOExample example=new AdUserPOExample();
        example.createCriteria().andOrgIDEqualTo(id);
        long c1=this.mixedDS.txDs().mapper().countByExample(example);
        if (c1>0){
            log.error("组织id {}下有员工，不能删除！",id);
            throw BizException.exception("组织id {0}下有员工，不能删除！",id);
        }
        //删除组织下数据
        AdOrgPOExample orgPOExample=new AdOrgPOExample();
        orgPOExample.createCriteria().andPidEqualTo(id);
        List<AdOrgPO> children=this.mixedDS.txDs().mapper().selectByExample(orgPOExample);
        for (AdOrgPO child : children) {
            this.deleteOrg(child.getId());
        }

        AdOrgPO adOrgPO=new AdOrgPO();//this.mixedDS.txDs().mapper().selectByPrimaryKey(AdUserPO.class,id);
        adOrgPO.setId(id);
        adOrgPO.setIsDel(true);
        adOrgPO.setUpdateBy(SysSession.getUser().getLoginName());
        adOrgPO.setUpdateTime(new Date());
        int c2=this.mixedDS.txDs().mapper().updateByPrimaryKeySelective(adOrgPO);
        log.info("逻辑删除组织 id {}",id);
        return c2;
    }

    @Override
    @MultiDs
    @Transactional
    public void orgSort(List<OrgBO> orgBOList) {
        if (null!=orgBOList){
            for (int i = 0; i < orgBOList.size(); i++) {
                OrgBO orgBO=orgBOList.get(i);
                AdOrgPO adOrgPO=new AdOrgPO();
                adOrgPO.setId(orgBO.getId());
                adOrgPO.setPriority((double)i);
                this.mixedDS.txDs().mapper().updateByPrimaryKeySelective(adOrgPO);
                List<OrgBO> children=orgBO.getChildren();
                this.orgSort(children);//递归子列表
            }
            log.info("菜单排序 size :{}",orgBOList.size());
        }
    }

    @Override
    public List<Long> getOrgIDTreeList(Long rootID) {
        AdOrgPOExample example=new AdOrgPOExample();
        List<AdOrgPO> orgPOList=this.mixedDS.txDs().mapper().selectByExample(example);
        List<Long> ids=this.getOrgIDTreeList(rootID,orgPOList);
        ids.add(rootID);

        return ids;
    }

    private List<Long> getOrgIDTreeList(Long rootID, List<AdOrgPO> orgPOList) {
        List<Long> ids=new ArrayList<>();
        List<AdOrgPO> children=orgPOList.stream().filter(org->org.getPid().equals(rootID)).collect(Collectors.toList());
        for (AdOrgPO child : children) {
            ids.add(child.getId());
            List<Long> childIDList=getOrgIDTreeList(child.getId(),orgPOList);
            ids.addAll(childIDList);
        }
        return ids;
    }
}
